from manimlib.imports import *

def hasTex(str):#例如str="床前$x^2$明月光"
    #专门用来处理Tex包含的字符串
    TextPos=0
    a=0#
    output=VGroup()
    dollarPos=str.find("$")#
    if(dollarPos>=0):
        while(dollarPos>=0 and TextPos>=0):#
            print(TextPos,dollarPos)
            if(dollarPos>TextPos):#
                print("1",str[TextPos:dollarPos])
                b=Text(str[TextPos:dollarPos])
                output.add(b)  # add
            dollarPos=dollarPos+1#3
            TextPos=str.find("$",dollarPos)#6
            if(TextPos>=0 ):
                print("2",str[dollarPos:TextPos])
                b=TexMobject(str[dollarPos:TextPos])
                b.scale(2)
                output.add(b)
            TextPos=TextPos+1 #9 18
            dollarPos = str.find("$",TextPos)#13 21
            if(dollarPos==len(str)-1 or dollarPos == -1):#到达边界或找不到
                print("3",str[TextPos:])
                b=(Text(str[TextPos:]))
                output.add(b)
                break
    else:
        output.add(Text(str))
    print(f"outputlen:{len(output)}")
    b=output[0]
    if(len(output)>1):
        for i in output[1:]:
            i.next_to(b,RIGHT, buff=0.2)
            b=i
    return output
def TexText(*key):
    output=VGroup()
    a=(hasTex(key[0]))
    output.add(a)
    if(len(key)>1):
        for i  in key[1:]:
            b=hasTex(i)
            b.next_to(a,RIGHT, buff=0.1)
            output.add(b)
            a=b
    output.scale(.5).move_to([0,0,0])
    return output
def TexTextflat(*key):
    output=VGroup()
    a=key[0]
    if("$" in a):
        output.add(TexMobject(a[1:len(a)-1]))
        output[-1].scale(2)
    else:
        output.add(Text(a))
    if(len(key)>1):
        for i  in key[1:]:
            if ("$" in i):
                output.add(TexMobject(i[1:len(i)-1]))
                output[-1].scale(2)
            else:
                output.add(Text(i))
    a=output[0]
    if(len(output)>1):
        for i in output[1:]:
            i.next_to(a,RIGHT, buff=0)
            i.align_to(a[0][-1],DOWN)
            a=i
    output.scale(.5).move_to([0,0,0])
    return output

class test(Scene):
    def construct(self):
        self.textBoxDict={
           "微分算子的定义1":{
               "form":TexMobject("Df=f'(f')'f''DDD^2(f)^{''\\cdots'}f^{(n)}DD\\cdots DD^nD\\cdot D"),
                "title":TextMobject("微分算子的","定义",":"),
                "title2":TextMobject("算子的","乘法性质"),
                "title3":TextMobject("算子的","加法性质"),
                "移动求导符号":TextMobject("移动求导符号$'$,到$f$前面,变成$D$"),
                "这就是微分算子":TextMobject("这个$D$就是","微分算子"),
                "是求导运算":TextMobject("他表示对$f$的","求导运算",",是一个","运算符号"),
                "同时又像数":TextMobject("但这个符号又像","数","一样,本身也有一些","运算"),
                "算子乘法运算1":TextMobject("比如我们对$f'$继续求导,","则等式右边变成"),
                "算子乘法运算2":TextMobject("那么左边就出现了两个D,","他们可以看作彼此相乘,","写作"),
                "算子乘法运算3":TextMobject("所以如果有n阶求导,","那就有n个D相乘,","写作")
            }
        }
        self.微分算子的定义1()
    def 微分算子的定义1(self):
        title=self.textBoxDict["微分算子的定义1"]["title"]
        title2=self.textBoxDict["微分算子的定义1"]["title2"]
        title3 = self.textBoxDict["微分算子的定义1"]["title3"]
        form=self.textBoxDict["微分算子的定义1"]["form"][0]
        移动求导符号=self.textBoxDict["微分算子的定义1"]["移动求导符号"]
        这就是微分算子=self.textBoxDict["微分算子的定义1"]["这就是微分算子"]
        是求导运算=self.textBoxDict["微分算子的定义1"]["是求导运算"]
        同时又像数=self.textBoxDict["微分算子的定义1"]["同时又像数"]
        算子乘法运算1=self.textBoxDict["微分算子的定义1"]["算子乘法运算1"]
        算子乘法运算2=self.textBoxDict["微分算子的定义1"]["算子乘法运算2"]
        算子乘法运算3=self.textBoxDict["微分算子的定义1"]["算子乘法运算3"]
        算子乘法运算x= VGroup(算子乘法运算1,算子乘法运算2,算子乘法运算3)
        #设置组
        g={
            "f'":VGroup(form[3:5]),
            #"f'copy":VGroup(form[3:5].copy()),
            "Df=":VGroup(form[0:3]),
            "=left":VGroup(form[0:2]),
            "=right":VGroup(form[3:]),
            "''":VGroup(form[6][1:]),
            "nexttorect1":VGroup(移动求导符号,是求导运算,同时又像数,算子乘法运算x),
            "setcoloryellow":VGroup(这就是微分算子[1],是求导运算[1],是求导运算[3],同时又像数[1],title[1],同时又像数[3],title2[1],title3[1]),
            "title":VGroup(title,title2,title3),
            "Tobject":移动求导符号,
            "Dform":VGroup(form[0],form[7],form[8],form[11],form[12],form[13]),
            "'form":VGroup(VGroup(form[3:5]),form[5],form[6],form[9],form[10])
        }
        #位置颜色大小,注意位置前后关系,颜色无所谓
        g["title"].to_corner(LEFT+UP)
        form[2].move_to([0,0,0])
        g["=left"].next_to(form[2],LEFT,buff=.2)
        g["=right"].next_to(form[2],RIGHT,buff=.2)
        g["setcoloryellow"].set_color_by_gradient(YELLOW,BLUE)
        for el in g["Dform"]:
            el.next_to(form[1],LEFT,buff=.1)
        for el in g["'form"]:
            el.next_to(form[2],RIGHT,buff=.1)
        #助记图形
        rect1=SurroundingRectangle(form[4])
        rect2=SurroundingRectangle(form[0])
        #所需位置
        这就是微分算子.next_to(rect2, DOWN, buff=.2).scale(.5)
        g["nexttorect1"].next_to(rect1, UP, buff=.2).scale(.5)
        #播放
        #微分算子的定义
        self.play(Write(title))
        #移动求导符号
        self.play(Write(g["f'"]))
        self.play(ShowCreation(rect1))
        self.play(Write(g["Tobject"]))#引用移动求导符号
        self.wait(2)
        self.play(
            TransformFromCopy(g["f'"],g["Df="]),#TransformFromCopy将a的副本变换到b,到时可以将b 以FadeOut消除
            TransformFromCopy(rect1,rect2)
        )
        self.wait()
        #这就是微分算子
        self.play(Write(这就是微分算子))
        self.wait(3)
        #是求导运算
        self.play( Transform(g["Tobject"],是求导运算))
        self.wait(2)
        self.play( Transform(g["Tobject"],同时又像数))
        self.wait(2)
        #算子的乘法性质
        self.play(Transform(title,title2),FadeOut(rect1),FadeOut(rect2),FadeOut(这就是微分算子))
        self.wait()
        self.play(Transform(g["Tobject"],算子乘法运算1[0]))
        self.wait()
        self.add(算子乘法运算1[0])
        self.play(Transform(g["Tobject"],算子乘法运算1[1]))
        self.play(Transform(g["f'"],form[5]))
        self.wait()
        self.play(Transform(g["f'"],form[6]))
        self.wait()
        self.remove(算子乘法运算1[0])
        self.play(Transform(g["Tobject"],算子乘法运算2[0]),FadeOut(form[0]),TransformFromCopy(g["''"],form[7]))
        self.wait(2)
        self.add(算子乘法运算2[0])
        self.play(Transform(g["Tobject"],算子乘法运算2[1]),Transform(form[7],form[13]))
        self.add(算子乘法运算2[1])
        self.wait()
        self.play(Transform(g["Tobject"],算子乘法运算2[2]),Transform(form[7],form[8]))
        self.wait()
        self.play(FadeOut(算子乘法运算2) ,Transform(g["Tobject"],算子乘法运算3[0]))
        self.play(Transform(g["f'"],form[9]))
        self.wait()
        self.add(算子乘法运算3[0])
        self.play(Transform(g["Tobject"],算子乘法运算3[1]),Transform(g["f'"],form[10]))
        self.play(FadeOut(form[7]),TransformFromCopy(g["f'"],form[11]))
        self.wait()
        self.add(算子乘法运算3[1])
        self.play(Transform(g["Tobject"],算子乘法运算3[2]),Transform(form[11],form[12]))
        self.wait(3)

class test2(Scene):
    def construct(self):
        self.textBoxDict={
           "微分算子的定义1":{
               "form":TexMobject(
                   "D",#0
                   "f",#1
                   "=",#2
                   "f",#3
                   "'",#4
                   "(f')'",#5
                   "f''",#6
                   "DD",#7
                   "D^2",#8
                   "(f)^{''\\cdots'}",#9
                   "f^{(n)}",#10
                   "DD\\cdots  D",#11
                   "D^n",#12
                   "D\\cdot D"#13
                ),
                "title":TextMobject("微分算子的","定义",":"),
                "title2":TextMobject("算子的","乘法性质"),
                "title3":TextMobject("算子的","加法性质"),
                "移动求导符号":TextMobject("移动求导符号$'$,到$f$前面,变成$D$"),
                "这就是微分算子":TextMobject("这个$D$就是","微分算子"),
                "是求导运算":TextMobject("他表示对$f$的","求导运算",",是一个","运算符号"),
                "同时又像数":TextMobject("但这个符号又像","数","一样,本身也有一些","运算"),
                "算子乘法运算1":TextMobject("比如我们对$f'$继续求导,","则等式右边变成"),
                "算子乘法运算2":TextMobject("那么左边就出现了两个D,","他们可以看作彼此相乘,","写作"),
                "算子乘法运算3":TextMobject("所以如果有n阶求导,","那就有n个D相乘,","写作")
            }
        }
        self.微分算子的定义1()
    def 微分算子的定义1(self):
        title=self.textBoxDict["微分算子的定义1"]["title"]
        title2=self.textBoxDict["微分算子的定义1"]["title2"]
        title3 = self.textBoxDict["微分算子的定义1"]["title3"]
        form=self.textBoxDict["微分算子的定义1"]["form"]
        移动求导符号=self.textBoxDict["微分算子的定义1"]["移动求导符号"]
        这就是微分算子=self.textBoxDict["微分算子的定义1"]["这就是微分算子"]
        是求导运算=self.textBoxDict["微分算子的定义1"]["是求导运算"]
        同时又像数=self.textBoxDict["微分算子的定义1"]["同时又像数"]
        算子乘法运算1=self.textBoxDict["微分算子的定义1"]["算子乘法运算1"]
        算子乘法运算2=self.textBoxDict["微分算子的定义1"]["算子乘法运算2"]
        算子乘法运算3=self.textBoxDict["微分算子的定义1"]["算子乘法运算3"]
        算子乘法运算x= VGroup(算子乘法运算1,算子乘法运算2,算子乘法运算3)
        #设置组
        g={
            "f'":VGroup(form[3:5]),
            #"f'copy":VGroup(form[3:5].copy()),
            "Df=":VGroup(form[0:3]),
            "=left":VGroup(form[0:2]),
            "=right":VGroup(form[3:]),
            "''":VGroup(form[6][1:]),
            "nexttorect1":VGroup(移动求导符号,是求导运算,同时又像数,算子乘法运算x),
            "setcoloryellow":VGroup(这就是微分算子[1],是求导运算[1],是求导运算[3],同时又像数[1],title[1],同时又像数[3],title2[1],title3[1]),
            "title":VGroup(title,title2,title3),
            "Tobject":移动求导符号,
            "Dform":VGroup(form[0],form[7],form[8],form[11],form[12],form[13]),
            "'form":VGroup(VGroup(form[3:5]),form[5],form[6],form[9],form[10])
        }
        #位置颜色大小,注意位置前后关系,颜色无所谓
        g["title"].to_corner(LEFT+UP)
        form[2].move_to([0,0,0])
        g["=left"].next_to(form[2],LEFT,buff=.2)
        g["=right"].next_to(form[2],RIGHT,buff=.2)
        g["setcoloryellow"].set_color_by_gradient(YELLOW,BLUE)
        for el in g["Dform"]:
            el.next_to(form[1],LEFT,buff=.1)
        for el in g["'form"]:
            el.next_to(form[2],RIGHT,buff=.1)
        #助记图形
        rect1=SurroundingRectangle(form[4])
        rect2=SurroundingRectangle(form[0])
        #所需位置
        这就是微分算子.next_to(rect2, DOWN, buff=.2).scale(.5)
        g["nexttorect1"].next_to(rect1, UP, buff=.2).scale(.5)
        #播放
        #微分算子的定义
        self.play(Write(title))
        #移动求导符号
        self.play(Write(g["f'"]))
        self.play(ShowCreation(rect1))
        self.play(Write(g["Tobject"]))#引用移动求导符号
        self.wait(2)
        self.play(
            TransformFromCopy(g["f'"],g["Df="]),#TransformFromCopy将a的副本变换到b,到时可以将b 以FadeOut消除
            TransformFromCopy(rect1,rect2)
        )
        self.wait()
        #这就是微分算子
        self.play(Write(这就是微分算子))
        self.wait(3)
        #是求导运算
        self.play( Transform(g["Tobject"],是求导运算))
        self.wait(2)
        self.play( Transform(g["Tobject"],同时又像数))
        self.wait(2)
        #算子的乘法性质
        self.play(Transform(title,title2),FadeOut(rect1),FadeOut(rect2),FadeOut(这就是微分算子))
        self.wait()
        self.play(Transform(g["Tobject"],算子乘法运算1[0]))
        self.wait()
        self.add(算子乘法运算1[0])
        self.play(Transform(g["Tobject"],算子乘法运算1[1]))
        self.play(Transform(g["f'"],form[5]))
        self.wait()
        self.play(Transform(g["f'"],form[6]))
        self.wait()
        self.remove(算子乘法运算1[0])
        self.play(Transform(g["Tobject"],算子乘法运算2[0]),FadeOut(form[0]),TransformFromCopy(g["''"],form[7]))
        self.wait(2)
        self.add(算子乘法运算2[0])
        self.play(Transform(g["Tobject"],算子乘法运算2[1]),Transform(form[7],form[13]))
        self.add(算子乘法运算2[1])
        self.wait()
        self.play(Transform(g["Tobject"],算子乘法运算2[2]),Transform(form[7],form[8]))
        self.wait()
        self.play(FadeOut(算子乘法运算2) ,Transform(g["Tobject"],算子乘法运算3[0]))
        self.play(Transform(g["f'"],form[9]))
        self.wait()
        self.add(算子乘法运算3[0])
        self.play(Transform(g["Tobject"],算子乘法运算3[1]),Transform(g["f'"],form[10]))
        self.play(FadeOut(form[7]),TransformFromCopy(g["f'"],form[11]))
        self.wait()
        self.add(算子乘法运算3[1])
        self.play(Transform(g["Tobject"],算子乘法运算3[2]),Transform(form[11],form[12]))
        self.wait(3)


class test3(Scene):
    # 测试计算表达式移位行不行
    def construct(self):
        f=TexMobject("Df=f'(f')'f''DDD^2")#7
        onleft=VGroup(f[0:2])
        onright=VGroup(f[3:])
        f[2].move_to([0, 0, 0])
        onleft.next_to(f[2],LEFT,buff=.2)
        onright.next_to(f[2],RIGHT,buff=.2)
        f[1].next_to(f[2],LEFT,buff=0.2)
        f[3].next_to(f[2],RIGHT,buff=0.2)
        f[4].next_to(f[2],RIGHT,buff=0.2)
        f[5].move_to(f[3])
        f[6].next_to(f[1],LEFT,buff=0.2)
        f[7].next_to(f[1],LEFT,buff=0.2)

        self.play(
            Write(f[3])
        )
        self.wait()
        p1=f[3].copy()
        fself=VGroup(f[0],f[1])
        self.play(
            Transform(p1,fself),Write(f[2])
        )
        self.wait()
        self.play(
            Transform(f[3],f[4])
        )
        self.wait()
        self.play(
            Transform(f[3], f[5])
        )
        fpp=VGroup(f[3][1:])
        self.wait()
        self.play(
            FadeOut(p1[0]),FadeOut(f[0]),
            TransformFromCopy(fpp,f[6])
        )
        self.wait()
        self.play(
            Transform(f[6],f[7])
        )
        self.wait(2)

class test4(Scene):
    def construct(self):
        a=TexText(r"床前$x^2$明月光$\sqrt{b^2-4ac}$$\int_{a}^{b}\frac{c}{d}\mathrm{d}x$","$x^2$","疑是地上霜")
        self.play(Write(a))
        self.play(FadeOut(a))
        for i in a:
            for j in i:
                for k in j:

                    self.play(ShowCreation(k))
        self.wait(3)
class test5(Scene):
    def construct(self):
        #TODO 理解target语言
        text=Text("你好吗大傻逼").to_edge()
        text2=Text("hellSB")
        text3= Text("okSB").to_edge(RIGHT)
        text.generate_target(True)
        text.target= text2
        text2.generate_target(True)
        text2.target= text3
        self.play(MoveToTarget(text))
        self.wait(1)
        self.play(MoveToTarget(text2))
        self.wait(2)

class LaggedStartTest(Scene):
    def construct(self):
        circles = VGroup()
        for i in range(4):
            c = Circle(radius=0.3)
            c.move_to((i - 2) * RIGHT)
            circles.add(c)
        circles2 = VGroup()
        for i in range(4):
            c = Circle(radius=0.3)
            c.move_to((i - 2) * RIGHT)
            circles2.add(c)
        self.play(LaggedStartMap(
            ShowCreation,
            circles,
            lag_ratio=0.2,)
        )
        self.wait()
class FormulaColor3Fixed2(Scene):
    def construct(self):
        text = TexMobject("(D^{n}(a_{1}f_{1})+D^{n}(a_{2}f_{2})+\cdots+D^{n}(a_{m}f_{m}))"
                          ,stroke_width=.1)
        #text[6].set_color(WHITE)
        self.play(Write(text))
        self.play(FadeOut(text))
        print(len(text[0]))
        for i,j in zip(text[0],[RED,BLUE,GREEN,YELLOW,PINK,ORANGE,PURPLE,MAROON,TEAL]):
            print(len(i))
            i.set_color(j)
            self.play(Write(i))
        self.wait(3)

class test6(Scene):
    def 变换(self, 来, 去, 消=None, 复=True):
        '''
        用于文字的运动
        :param 来: from
        :param 去: to
        :param 消: fadeout
        :param 复: fromcopy or single transform
        :return:
        '''
        播 = TransformFromCopy if 复 else Transform
        if 消:
            self.play(播(来, 去), FadeOut(消))
        else:
            self.play(播(来, 去))
    def construct(self):
        t1 = TexMobject(r"(a_{1}f_{1}+a_{2}f_{2}+\cdots+a_{m}f_{m})^{(n)}").set_color(YELLOW)
        t2 = TexMobject(r"((a_{1}f_{1})^{(n)}+(a_{2}f_{2})^{(n)}+\cdots+(a_{m}f_{m})^{(n)})").set_color(GREEN).align_to(
            t1,LEFT)
        t3 = TexMobject(r"(D^{n}(a_{1}f_{1})+D^{n}(a_{2}f_{2})+\cdots+D^{n}(a_{m}f_{m}))")
        self.play(Transform(t1,t2))
        self.wait()
        self.play(Transform(t1,t3))
        self.wait()
        self.play(Indicate(t1[0][1:4], scale_value=2),
                  Indicate(t1[0][11:14], scale_value=2),
                  Indicate(t1[0][26:28], scale_value=2),
                  )
        self.wait(2)


class 父基(Scene):
    def Tplay(self,来,去,消=None,复=True):
        '''
        :param 来: from
        :param 去: to
        :param 消: fadeout
        :param 复: fromcopy or single transform
        :return:
        '''
        播=TransformFromCopy if 复 else Transform
        if 消:
            self.play(播(来,去),FadeOut(消))
        else:
            self.play(播(来, 去))
class 父类(父基):
    def construct1(self):
        textBoxDict = VGroup(Text("你好小朋友"),Text("你好大朋友"))
        textBoxDict[0].to_edge(LEFT)
        textBoxDict[1].to_edge(RIGHT)
        return textBoxDict

class 子类(父类):
    # def __init__(self, **kwargs):
    #     self.play(Write(self.textBoxDict))
    def construct(self):
        textBoxDict=super().construct1()
        # self.play(Write(self.textBoxDict))
        self.Tplay(textBoxDict[0],textBoxDict[1],复=False)
        self.wait(3)
class 子类2(父类):
    CONFIG ={
        "dir":r"D:\manim\manim_docker_diagram.png"
    }
    def construct(self):
        textBoxDict = super().construct1()
        self.set_camera_background( ImageMobject(self.dir))
        # self.play(Write(self.textBoxDict))
        self.wait(3)

class 子类3(父类):
    def construct(self):
        self.play(Write(self.textBoxDict))
class HomotopyExample(Scene):
    def construct(self):
        def plane_wave_homotopy(x, y, z, t):
            return [x+np.cos(2*PI*t), y + np.sin(2*PI*t), z]

        mobjects=VGroup(
            TextMobject("Text").scale(3),
            Square(),
        ).arrange_submobjects(RIGHT,buff=2)

        self.add(mobjects)
        self.play(
            *[Homotopy(
                plane_wave_homotopy,
                mob
            ) for mob in mobjects]
        )
        self.wait(0.3)
class PhaseFlowExample(Scene):
    def construct(self):
        def func(t):
            return t*0.5*RIGHT

        mobjects=VGroup(
            TextMobject("Text").scale(3),
            Square(),
        ).arrange_submobjects(RIGHT,buff=2)

        self.play(
            *[PhaseFlow(
                func, mob,
                run_time = 2,
            )for mob in mobjects]
        )

        self.wait()
class MoveAlongPathExample(Scene):
    def construct(self):
        line=Line(ORIGIN,RIGHT*FRAME_WIDTH,buff=1)
        line.move_to(ORIGIN)
        dot=Dot()
        dot.move_to(line.get_start())

        self.add(line,dot)
        self.play(
            MoveAlongPath(dot,line)
        )
        self.wait(0.3)
class UpdatersExample(Scene):
    def construct(self):
        decimal = DecimalNumber(
            1,
            show_ellipsis=True,
            num_decimal_places=5,
            include_sign=True,
        )
        square = Square().to_edge(UP)

        decimal.add_updater(lambda d: d.next_to(square, RIGHT))
        decimal.add_updater(lambda d: d.set_value(square.get_center()[1]))
        self.add(square, decimal)
        self.play(
            square.to_edge, DOWN,
            rate_func=wiggle,
            run_time=5,
        )
        self.wait()